/*
 * Copyright Aristool AG Switzerland
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License. 
 * You may obtain a copy of the License at 
 * 
 * http://www.apache.org/licenses/LICENSE-2.0 
 * 
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 * See the License for the specific language governing permissions and 
 * limitations under the License.
 */
package org.opprua.tidy.util;

import java.io.InputStream;

import org.opprua.tidy.gens.GBean;
import org.opprua.tidy.gens.GVar;
import org.opprua.tidy.gens.Gtor;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * TODO: add Java doc
 * 
 * Prepared for first commit: 15.04.2007
 * 
 * @author Lin Li
 */
public class BuildBean {

  private String destDir = "";
  private String packageName = "";

  private BuildBean() {
  }

  public void doThem(Element doc) {
    String s = doc.getAttribute("destDir");
    if (s != null && s.trim().length() > 0) {
      this.destDir = s;
    }

    s = doc.getAttribute("package");
    if (s != null && s.trim().length() > 0) {
      this.packageName = s;
    }

    NodeList nl = doc.getElementsByTagName("bean");
    for (int i = 0; i < nl.getLength(); i++) {
      Element e = (Element) nl.item(i);
      doBean(e);
    }
  }

  private void addAnnotations(Gtor v, Element t) {
    NodeList nl = t.getChildNodes();
    for (int i = 0; i < nl.getLength(); i++) {
      Node n = nl.item(i);
      if (n.getNodeType() != Node.ELEMENT_NODE) continue;
      Element e = (Element) n;
      if (!e.getTagName().equals("annotation")) continue;
      String p = e.getAttribute("place");
      String a = XReader.collectText(e);
      if (v instanceof GVar) {
        GVar f = (GVar) v;
        if ("getter".equals(p)) {
          f.annoteGetter(a);
        } else if ("setter".equals(p)) {
          f.annoteSetter(a);
        } else {
          f.annotate(a);
        }
      } else {
        v.annotate(a);
      }
    }
  }

  private void doBean(Element e) {
    String pack = this.packageName;
    String name = e.getAttribute("name");
    String s = e.getAttribute("package");

    if (s != null && s.trim().length() > 0) {
      pack = s;
    }

    GBean gen = new GBean(name);
    gen.comment(XReader.collectText(e));
    addAnnotations(gen, e);
    gen.setPackage(pack);

    String exts = e.getAttribute("extends");
    if (exts != null && exts.length() > 0) {
      gen.setExtends(exts);
    }

    String uid = e.getAttribute("uid");
    if (uid != null && uid.length() > 0) {
      gen.addField("public static final", "long", "serialVersionUID", uid);
    }

    String imps = e.getAttribute("implements");
    if (imps == null || imps.length() == 0) {
      if (exts == null || exts.length() == 0) {
        gen.setImplements("java.io.Serializable, Cloneable");
      }
    } else {
      gen.setImplements(imps);
    }

    NodeList nl = e.getElementsByTagName("import");
    for (int i = 0; i < nl.getLength(); i++) {
      Element t = (Element) nl.item(i);
      gen.addImport(XReader.collectText(t));
    }

    nl = e.getElementsByTagName("entry");
    for (int i = 0; i < nl.getLength(); i++) {
      Element t = (Element) nl.item(i);
      String n = t.getAttribute("name");
      String type = t.getAttribute("type");
      String defaultValue = t.getAttribute("defaultValue");
      String isArray = t.getAttribute("isArray");
      GVar v = new GVar("private", type, n, defaultValue);
      v.comment(XReader.collectText(t));
      if (isArray.equals("true")) {
        v.setArrayType();
      }
      addAnnotations(v, t);

      gen.beanField(v);
    }
    gen.dump(destDir);
  }

  public static void main(String[] args) {
    for (int i = 0; i < args.length; i++) {
      System.out.println("Processing definition file: " + args[i]);
      generate(args[i]);
    }
    System.out.println("Bean generation finished. Have fun.");
  }

  public static void generate(Element doc) {
    new BuildBean().doThem(doc);
  }

  public static void generate(InputStream doc) {
    generate(XReader.getDocRoot(doc));
  }

  public static void generate(String doc) {
    generate(XReader.getDocRoot(doc));
  }
}
